From 0c4dcd9d576af0f410e1d3b38924420427b7b704 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Timm=20B=C3=A4der?= Date: Wed, 29 Apr 2020 09:28:17 +0200 Subject: [PATCH] add GtkArray Try to use stack space if we can and only fall back to the GPtrArray if we must. --- gtk/gtkarrayimplprivate.h | 100 ++++++++++++++++++++++++++++++++++++++ gtk/gtkmain.c | 33 +++++++------ 2 files changed, 118 insertions(+), 15 deletions(-) create mode 100644 gtk/gtkarrayimplprivate.h diff --git a/gtk/gtkarrayimplprivate.h b/gtk/gtkarrayimplprivate.h new file mode 100644 index 0000000000..0027aa5b3e --- /dev/null +++ b/gtk/gtkarrayimplprivate.h @@ -0,0 +1,100 @@ +#ifndef __GTK_ARRAY_IMPL_PRIVATE_H__ +#define __GTK_ARRAY_IMPL_PRIVATE_H__ + + +/* This is a dumbed-down GPtrArray, which takes some stack + * space to use. When using this, the general case should always + * be that the number of elements is lower than reversed_size. + * The GPtrArray should only be used in extreme cases. + */ + +typedef struct +{ + guint reserved_size; + guint len; + void **stack_space; + GPtrArray *ptr_array; + +} GtkArray; + + +static inline void +gtk_array_init (GtkArray *self, + void **stack_space, + guint reserved_size) +{ + self->reserved_size = reserved_size; + self->len = 0; + self->stack_space = stack_space; + self->ptr_array = NULL; +} + +static inline void * +gtk_array_index (GtkArray *self, + guint index) +{ + g_assert (index < self->len); + + if (G_LIKELY (!self->ptr_array)) + return self->stack_space[index]; + + return g_ptr_array_index (self->ptr_array, index); +} + +static inline void +gtk_array_add (GtkArray *self, + void *element) +{ + if (G_LIKELY (self->len < self->reserved_size)) + { + self->stack_space[self->len] = element; + self->len++; + return; + } + + /* Need to fall back to the GPtrArray */ + if (G_UNLIKELY (!self->ptr_array)) + { + guint i; + + self->ptr_array = g_ptr_array_new_full (self->reserved_size, NULL); + + /* Copy elements from stack space to GPtrArray */ + for (i = 0; i < self->len; i++) + g_ptr_array_add (self->ptr_array, self->stack_space[i]); + } + + g_ptr_array_add (self->ptr_array, element); + self->len++; /* We still count self->len */ +} + +static inline void +gtk_array_free (GtkArray *self, + GDestroyNotify element_free_func) +{ + guint i; + + if (G_LIKELY (!self->ptr_array)) + { + if (element_free_func) + { + for (i = 0; i < self->len; i++) + element_free_func (self->stack_space[i]); + } + + return; + } + + g_assert (self->ptr_array); + + if (element_free_func) + { + for (i = 0; i < self->ptr_array->len; i++) + element_free_func (g_ptr_array_index (self->ptr_array, i)); + } + + g_ptr_array_free (self->ptr_array, TRUE); +} + + +#endif diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index f8a6dfac35..518f3aefbf 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -95,6 +95,7 @@ #include "gdk/gdk-private.h" #include "gsk/gskprivate.h" #include "gsk/gskrendernodeprivate.h" +#include "gtkarrayimplprivate.h" #include @@ -1310,7 +1311,8 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel, double x, y; GtkWidget *prev; gboolean seen_ancestor; - GPtrArray *targets; + GtkArray target_array; + GtkWidget *stack_targets[16]; int i; if (old_target == new_target) @@ -1364,19 +1366,19 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel, widget = _gtk_widget_get_parent (widget); } - targets = g_ptr_array_new_full (16, NULL); + gtk_array_init (&target_array, (void**)stack_targets, 16); for (widget = new_target; widget; widget = _gtk_widget_get_parent (widget)) - g_ptr_array_add (targets, widget); + gtk_array_add (&target_array, widget); crossing.direction = GTK_CROSSING_IN; seen_ancestor = FALSE; - for (i = (int)targets->len - 1; i >= 0; i--) + for (i = (int)target_array.len - 1; i >= 0; i--) { - widget = g_ptr_array_index (targets, i); + widget = gtk_array_index (&target_array, i); - if (i < (int)targets->len - 1) - crossing.new_descendent = g_ptr_array_index (targets, i + 1); + if (i < (int)target_array.len - 1) + crossing.new_descendent = gtk_array_index (&target_array, i + 1); else crossing.new_descendent = NULL; @@ -1405,7 +1407,7 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel, gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE); } - g_ptr_array_free (targets, TRUE); + gtk_array_free (&target_array, NULL); } static GtkWidget * @@ -2130,11 +2132,12 @@ propagate_event_down (GtkWidget *widget, { gint handled_event = FALSE; GtkWidget *target = widget; - GPtrArray *widgets; + GtkArray widget_array; + GtkWidget *stack_widgets[16]; int i; - widgets = g_ptr_array_new_full (16, g_object_unref); - g_ptr_array_add (widgets, g_object_ref (widget)); + gtk_array_init (&widget_array, (void**)stack_widgets, 16); + gtk_array_add (&widget_array, g_object_ref (widget)); for (;;) { @@ -2142,16 +2145,16 @@ propagate_event_down (GtkWidget *widget, if (!widget) break; - g_ptr_array_add (widgets, g_object_ref (widget)); + gtk_array_add (&widget_array, g_object_ref (widget)); if (widget == topmost) break; } - i = (int)widgets->len - 1; + i = widget_array.len - 1; for (;;) { - widget = g_ptr_array_index (widgets, i); + widget = gtk_array_index (&widget_array, i); if (!_gtk_widget_is_sensitive (widget)) { @@ -2177,7 +2180,7 @@ propagate_event_down (GtkWidget *widget, i--; } - g_ptr_array_free (widgets, TRUE); + gtk_array_free (&widget_array, g_object_unref); return handled_event; } -- 2.30.2